
package player;
import helliker.id3.ID3v2FormatException;
import helliker.id3.MP3File;
import helliker.id3.Playlist;
import helliker.id3.PlaylistException;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.net.MalformedURLException;
import javax.media.ControllerEvent;
import javax.media.ControllerListener;
import javax.media.EndOfMediaEvent;
import javax.media.Format;
import javax.media.Manager;
import javax.media.MediaLocator;
import javax.media.NoPlayerException;
import javax.media.Player;
import javax.media.PrefetchCompleteEvent;
import javax.media.RealizeCompleteEvent;
import javax.media.Time;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.FloatControl;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JSlider;
import javax.swing.JWindow;
import javax.swing.Timer;
import javax.swing.filechooser.FileFilter;

import com.sun.media.controls.AudioControl;
import com.sun.media.controls.BooleanControl;

import sun.audio.AudioData;
import sun.audio.AudioDataStream;

/**
 * Player GUI
 * + Open playlist
 * + Open playlist manager
 * + Support: Play/Pause/Stop/Previous/Next function
 * + Display progress and name of playing song
 *
 */
public class JavaPlayer extends JWindow implements ActionListener,ControllerListener,MouseMotionListener, Runnable {
	private Playlist playlist;
	private Player player = null;
	private JPanel mainPanel = null;
	private JProgressBar progressBar = null;
	private String fileTitle = "";
	private float filetime;//add
	
	private Thread playThread = null;
	Timer timer;//add
	
	
	private int mx,my;
	private  int draggedAtX, draggedAtY;
	boolean change= true;
	
	
	
	
	
	public JavaPlayer() {
		super();
		mainPanel = new JPanel(new FlowLayout(FlowLayout.LEADING,-1,1));
		
		mainPanel.setBorder(BorderFactory.createRaisedBevelBorder());
		mainPanel.addMouseMotionListener(this);
		
		Settings.loadSettings();
		//setBounds(Settings.getMainWindowRect());
		// set size for panel
		setBounds(300, 300, 500, 25);
		buildToolbar();
		add(mainPanel);//
		setVisible(true);//setvisible
		playlist = new Playlist();
		File playlistFile = new File(Settings.getPlaylistDirectory(),	Settings.getPlaylistFile());
		if(playlistFile.exists() && playlistFile.isFile()) {
			progressBar.setString("Loading Playlist...");
			try {
				playlist.loadFromFile(playlistFile);
			}
			catch(IOException ex) {
				errorMessage(ex.getMessage());
			}
			catch(PlaylistException ex) {
				errorMessage(ex.getMessage());
			}
			progressBar.setString("");
		}
		
	}
	
	/**
	 * build Player User Interface (GUI)
	 */
	private void buildToolbar() {
		
		JButton button ;//chua add ten button
		button = new JButton(new ImageIcon(getClass().getClassLoader().getResource("icons/Playlist16.gif")));
		button.setPreferredSize(new Dimension(20,20));
		button.setActionCommand("Open Playlist");
		button.addActionListener(this);
		mainPanel.add(button);
		
		button = new JButton(new ImageIcon(getClass().getClassLoader().getResource("icons/Manager16.gif")));
		button.setPreferredSize(new Dimension(20,20));
		button.setActionCommand("Playlist Manager");
		button.addActionListener(this);
		mainPanel.add(button);
		
		button = new JButton(new ImageIcon(getClass().getClassLoader().getResource("icons/Play16.gif")));
		button.setPreferredSize(new Dimension(20,20));
		button.setActionCommand("Play");
		button.addActionListener(this);
		mainPanel.add(button);
		
		button = new JButton(new ImageIcon(getClass().getClassLoader().getResource("icons/Pause16.gif")));
		button.setPreferredSize(new Dimension(20,20));
		button.setActionCommand("Pause");
		button.addActionListener(this);
		mainPanel.add(button);
		
		button = new JButton(new ImageIcon(getClass().getClassLoader().getResource("icons/Stop16.gif")));
		button.setPreferredSize(new Dimension(20,20));
		button.setActionCommand("Stop");
		button.addActionListener(this);
		mainPanel.add(button);
		
		button = new JButton(new ImageIcon(getClass().getClassLoader().getResource("icons/Previous16.gif")));
		button.setPreferredSize(new Dimension(20,20));
		button.setActionCommand("Previous");//add
		button.addActionListener(this);
		mainPanel.add(button);
		
		button = new JButton(new ImageIcon(getClass().getClassLoader().getResource("icons/Next16.gif")));
		button.setPreferredSize(new Dimension(20,20));
		button.setActionCommand("Next");//add
		button.addActionListener(this);//add
		mainPanel.add(button);
		
		//add button Mute   <An Tang>
		button=new JButton(new ImageIcon(getClass().getClassLoader().getResource("icons/Volume.gif")));
		button.setPreferredSize(new Dimension(20,20));
		button.setActionCommand("Volume");
		button.addActionListener(this);
		mainPanel.add(button);
		
		//add button increase  <An Tang>
		button= new JButton(new ImageIcon(getClass().getClassLoader().getResource("icons/increase.gif")));
		button.setPreferredSize(new Dimension(20,20));
		button.setActionCommand("Increase");
		button.addActionListener(this);
		mainPanel.add(button);
		
		//add button decrease
		button= new JButton(new ImageIcon(getClass().getClassLoader().getResource("icons/decrease.jpg")));
		button.setPreferredSize(new Dimension(20,20));
		button.setActionCommand("Decrease");
		button.addActionListener(this);
		mainPanel.add(button);
		
		
		mainPanel.add(Box.createHorizontalStrut(2));
		progressBar = new JProgressBar();
		progressBar.setPreferredSize(new Dimension(280,18));//add
		progressBar.setStringPainted(true);
		progressBar.setFont(new Font("Dialog",Font.BOLD,10));
		progressBar.setString("");
		mainPanel.add(progressBar);
		mainPanel.add(Box.createHorizontalStrut(2));
		
		
		
		
		
		button = new JButton(new ImageIcon(getClass().getClassLoader().getResource("icons/Exit16.gif")));
		button.setPreferredSize(new Dimension(20,20));
		button.setActionCommand("Exit");
		button.addActionListener(this);
		mainPanel.add(button);
		
		
		
		
		//add exit program
		button.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub
				System.exit(0);
			}
		});
		
		
	}

	/**
	 * Show error message  
	 * @param s : error message
	 */
	public void errorMessage(String s) {
		JOptionPane.showMessageDialog(null, s, "Error", JOptionPane.INFORMATION_MESSAGE);
	}
	
	/**
	 * Exit Application
	 */
	private void exitAction() {
		Settings.setMainWindowRect(getBounds());
		Settings.storeSettings();
		if(player != null) {
			player.removeControllerListener(this);
			player.stop();
			player.close();
			player = null;
		}
		if(playThread == null) {
			playThread = null;
		}
	}
	
	/**
	 * Show Playlist Manager Form
	 */
	private void managerAction() {
		if(playlist != null) {
			PlaylistManager manager = new PlaylistManager(this);
			manager.setVisible(true);
		}
	}
	
	/**
	 * Open existed playlist file (m3u...)
	 */
	private void playlistAction() {
		JFileChooser fileChooser = new JFileChooser(Settings.getPlaylistDirectory());
		fileChooser.setMultiSelectionEnabled(true);
		fileChooser.addChoosableFileFilter(new PlaylistFilter());
		if(fileChooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
			progressBar.setString("Loading Playlist...");
			playlist = new Playlist();
			try {
				File playlistFile = fileChooser.getSelectedFile();
				playlist.loadFromFile(playlistFile);
				Settings.setPlaylistDirectory(playlistFile.getParent());
				Settings.setPlaylistFile(playlistFile.getName());
			}
			catch(IOException ex) {
				errorMessage(ex.getMessage());
			}
			catch(PlaylistException ex) {
				errorMessage(ex.getMessage());
			}
			progressBar.setString("");
		}
	}
	
	public Playlist getPlaylist() {
		return playlist;
	}
	
	public void setPlaylist(Playlist p) {
		playlist = p;
	}
	
	public Player getPlayer() {
		return player;
	}
	
	/**
	 * Play current song in playlist
	 */
	public void play() {
		MP3File mp3File = null;
		int position = Settings.getPlaylistPosition();
		try {
			mp3File = (MP3File) playlist.get(position);
			fileTitle = mp3File.getTitle();
			//add
			filetime=mp3File.getPlayingTime();
			
			
		}
		catch(ID3v2FormatException ex) {
			errorMessage(ex.getMessage());
		}
		if(player == null) {
			try {
				File file = new File(mp3File.getPath());//add
				MediaLocator mediaLocator = new MediaLocator(file.toURL());
				player = Manager.createPlayer(mediaLocator);
				player.addControllerListener(this);
				progressBar.setString("Realizing...");
				player.realize();
			}
			catch(MalformedURLException ex) {
				errorMessage(ex.getMessage());
			}
			catch(NoPlayerException ex) {
				errorMessage(ex.getMessage());
			}
			catch(IOException ex) {
				errorMessage(ex.getMessage());
			}
		}
		else {
			player.start();
			progressBar.setString("Playing...");
		}
	}

	/**
	 * Pause playing song
	 */
	private void pause() {
		if(player != null) {
			MP3File mp3File = null;
			int position = Settings.getPlaylistPosition();
			try {
				mp3File = (MP3File) playlist.get(position);
				fileTitle = mp3File.getTitle();
				progressBar.setString( fileTitle + " Paused");
			}
			catch(ID3v2FormatException ex) {
				errorMessage(ex.getMessage());
			}
			player.stop();
		}
	}
	
	/**
	 * Stop playing song
	 */
	public void stop() {
		if(player != null) {
			player.removeControllerListener(this);
			player.stop();
			player.close();
			player = null;
		}
		if(playThread != null) {
			playThread = null;
		}
		progressBar.setValue(0);
		progressBar.setString("");
	}
	
	/**
	 * Play previous song in playlist
	 */
	private void previous() {
		int position = Settings.getPlaylistPosition();
		position--;
		Settings.setPlaylistPosition(position);
		if(player != null)
		stop();
		play();
	}
	
	/**
	 * Play next song in playlist
	 */
	private void next() {
		int position = Settings.getPlaylistPosition();
		position++;
		System.out.println("p"+position);
		Settings.setPlaylistPosition(position);
		if(player != null)
			stop();
		play();
	}
	
	//Mute and unMute volume   <An Tang> 
	public void volume(){
		
		if (player!=null) {
			if (change==true) {
				player.getGainControl().setMute(true);
				change=false;
			}else{
				player.getGainControl().setMute(false);
				change=true;
			}
			
		}
	}
	
	
	float volume;
	
	//increase volume   <Vu Phan>
	public void increase(){
		
		
		if (player!=null) {
		volume=player.getGainControl().getLevel();
		volume+=0.1f;
		player.getGainControl().setLevel((float)volume);
		
		}
		
	}
	
	// decrease volume    <Vu Phan>
	public void decrease(){
		
		
		if (player!=null) {
		 volume=player.getGainControl().getLevel();
		 volume-=0.1f;
		player.getGainControl().setLevel((float)volume);
		
		}
		
	}
	
	// Allow user to play random file in playlist  <AnTang>
	private void random(){
		int random=Settings.getPlaylistPosition();
		random=(int)(Math.random()*57);
		//int random2=(int)Math.random();
		Settings.setPlaylistPosition(random);
		System.out.println("r"+random);
		if (player!=null) 
			stop();
		play();
		
	}
	
	public static void main(String args[]) {
		new JavaPlayer();
	}
	
	public void actionPerformed(ActionEvent ev) {
		JButton button = (JButton) ev.getSource();
		String command = button.getActionCommand();
		if(command.equals("Exit")) 
			exitAction();
		else if(command.equals("Open Playlist"))
			playlistAction();
		else if(command.equals("Playlist Manager"))
			managerAction();
		else if(command.equals("Play"))
			play();
		else if(command.equals("Pause"))
			pause();
		else if(command.equals("Stop"))
			stop();
		else if(command.equals("Previous"))
			previous();
		else if(command.equals("Next"))
			next();
		else if (command.equals("Volume")) {
			volume();
		}
		else if (command.equals("Increase")) {
			increase();
		}
		else if (command.equals("Decrease")) {
			decrease();
		}
	}
	
	// Update GUI base on Event object
	public void controllerUpdate(ControllerEvent ev) {
		if(ev instanceof RealizeCompleteEvent) {
			player.prefetch();
			progressBar.setString("Prefetching...");
		}
		if(ev instanceof PrefetchCompleteEvent) {
			Time time = player.getDuration();
			progressBar.setMaximum((int) time.getSeconds());
			
			
			
			
					//progressBar.setString("Playing " + fileTitle);//add

					
			
			playThread = new Thread(this);
			playThread.start();
			player.getGainControl().setLevel(1);
			player.start();
		}
		if(ev instanceof EndOfMediaEvent) {
			player.removeControllerListener(this);
			player.stop();
			player.close();
			player = null;
			if(playThread != null) {
				playThread = null;
			}
			progressBar.setValue(0);
			//next();
			random();
		}
	}
	
	/**
	 * Catch mouse position to move the GUI	
	 */
	
	//the position of jplayer GUI is changes incorrectly when dragged by mouse  < AnTang>
	public void mouseDragged(MouseEvent ev) {
		//mouseMoved(ev);
		Point loc =getLocation();
		Point clk =ev.getPoint();
		Point pt = new Point(loc.x+clk.x-draggedAtX,loc.y+clk.y-draggedAtY);
		System.out.println(loc.x+" "+(loc.y+clk.y-draggedAtY));
		setLocation(pt);
		
		
	}
	
	public void mouseMoved(MouseEvent ev) {
		draggedAtX = ev.getX();
	   draggedAtY = ev.getY();
	}
	
	
	
	/**
	 * Update Progress bar base on played time
	 */
	public void run() {
		
		int second;
		int minutes = 0;
		int maxSecond ;
		int maxMinute;
		int secondDuration;
		int minuteDuration=0;
		
		while(playThread != null) {
			if(player != null) {
				//Time time = player.getMediaTime();
				//progressBar.setValue((int) time.getSeconds());
				
				
				// Display remaining time of now playing song    <An Tang>
				Time time1 = player.getMediaTime();
				Time time2 = player.getDuration();
				progressBar.setValue((int) time1.getSeconds());
				
				maxSecond = (int) time2.getSeconds();
				second = (int) time1.getSeconds();
				maxMinute = (int) time2.getSeconds() /60-minuteDuration;
				secondDuration = maxSecond - second;

				if(secondDuration %60 ==0 && secondDuration != maxSecond) {
					minuteDuration +=1;
				}
				if(secondDuration == maxSecond) {
					minuteDuration =0;
				}
				if(secondDuration%60 <10) {
					progressBar.setString("Playing "+fileTitle+"( " +maxMinute+":0"+secondDuration%60+" )");
				} else {
					progressBar.setString("Playing "+fileTitle+"( " +maxMinute+":"+secondDuration%60+" )");
				}
				try {
					playThread.sleep(500);
				}
				catch(InterruptedException ex) {}
			}
		}
	}
	
	/**
	 * Filter to open just *.m3u files
	 *
	 */
	class PlaylistFilter extends FileFilter{
		public boolean accept(File file) {
			if(file.isDirectory())
				return true;
			String s = file.getName().toLowerCase();
			if (s.endsWith(".m3u"))
				return true;
			return false;
		}
		public String getDescription() {
			return "Playlist Files";
		}
			
	}
	public void mouseClicked(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	public void mouseEntered(MouseEvent arg0) {
		// TODO Auto-generated method stub
	}

	public void mouseExited(MouseEvent arg0) {
		// TODO Auto-generated method stub

	}

	public void mousePressed(MouseEvent arg0) {
		// TODO Auto-generated method stub
	//draggedAtX = arg0.getX();
   // draggedAtY = arg0.getY();
		
	}

	public void mouseReleased(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}
}